package com.ouyunc.file.plugins.minio;


import com.ouyunc.common.constant.CommonConstant;
import com.ouyunc.common.constant.enums.FilePluginEnum;
import com.ouyunc.common.context.SpringContextHolder;
import com.ouyunc.common.utils.SnowflakeUtil;
import com.ouyunc.file.plugins.AbstractUploaderDownloader;
import com.ouyunc.file.plugins.base.UploadConfig;
import com.ouyunc.file.plugins.base.FileReturn;
import com.ouyunc.file.plugins.base.DownloadConfig;
import com.ouyunc.file.plugins.properties.FileProperties;
import io.minio.MinioClient;
import io.minio.ObjectWriteResponse;
import io.minio.PutObjectArgs;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;

/**
 * @Author fangzhenxun
 * @Description: minIo 插件
 * @Version V1.0
 **/
public class MinIoFilePlugin extends AbstractUploaderDownloader {
    private static final Logger log = LoggerFactory.getLogger(MinIoFilePlugin.class);
    private static final FileProperties fileProperties;

    private static MinioClient minioClient;

    // 静态初始化,注意：http与https的配置,这里不使用https
    static {
        fileProperties = SpringContextHolder.getBean(FileProperties.class);
        try {
            minioClient = MinioClient.builder()
                    .endpoint(fileProperties.getMinio().getEndpoint(), fileProperties.getMinio().getPort(), false)
                    .region(fileProperties.getMinio().getRegion())
                    .credentials(fileProperties.getMinio().getAccessKey(), fileProperties.getMinio().getSecretKey())
                    .build();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("minio client create fail!");
        }

    }


    @Override
    public FilePluginEnum pluginEnum() {
        return FilePluginEnum.MIN_IO;
    }

    @Override
    public void download(String fileUri, String fileName,  DownloadConfig config) {

    }

    /**
     * @Author fangzhenxun
     * @Description 直接将文件字节数组写到浏览器
     * @param bytes
     * @param fileName
     * @return void
     */
    @Override
    public void download(byte[] bytes, String fileName, DownloadConfig config) {
        long beginTime = System.currentTimeMillis();
        //从数据库查询该文件原始名称
        //获取当前response 对象
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletResponse response = servletRequestAttributes.getResponse();
        try(WritableByteChannel writableByteChannel = Channels.newChannel(response.getOutputStream())) {
            if (StringUtils.isNotEmpty(fileName)) {
                //application/pdf：pdf格式
                //application/msword ： Word文档格式
                //application/octet-stream: 二进制流格式
                //Content-disposition中attachment和inline的区别 Attachment-弹框下载， inline-内嵌网页（如果内嵌网页，content-type 必须设置具体格式不能为二进制流）
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, CommonConstant.UTF_8));
                if (config != null) {
                    // mime 类型
                    if (StringUtils.isNoneBlank(config.getContentType())) {
                        response.setContentType(config.getContentType());
                    }
                    // 请求头
                    if (MapUtils.isNotEmpty(config.getHeaderMap())) {
                        config.getHeaderMap().forEach((key, value)->{
                            response.setHeader(key, value);
                        });
                    }
                }
            }
            ByteBuffer buffer = ByteBuffer.wrap(bytes);
            writableByteChannel.write(buffer);
            buffer.clear();
        }catch (IOException e) {
            log.error("文件下载失败！");
            e.printStackTrace();
        }
        log.info("下载 cost time: {} ms" , (System.currentTimeMillis() - beginTime));
    }


    @Override
    public FileReturn upload(MultipartFile file, UploadConfig configItem) {
        try {
            log.info("minio 开始上传文件...");
            long fileSize = file.getSize();
            String originalFilename = file.getOriginalFilename();
            String[] fileRegex = originalFilename.split("\\.", -1);
            String fileSuffix = "." + fileRegex[fileRegex.length - 1];
            String contentType = file.getContentType();
            InputStream inputStream = file.getInputStream();
            String newFileName = SnowflakeUtil.nextId() + "_" + originalFilename;
            ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs.builder()
                    .bucket(configItem.getBucketName())
                    .object(configItem.getBucketPath() + newFileName)
                    .stream(inputStream, inputStream.available(), -1)
                    .contentType(contentType)
                    .build());
            String fileUrl = fileProperties.getMinio().getEndpoint() + ":" + fileProperties.getMinio().getPort() + "/" + configItem.getBucketName() + "/" + configItem.getBucketPath() + URLEncoder.encode(newFileName, CommonConstant.UTF_8);

            return new FileReturn(originalFilename, newFileName, fileSuffix, fileUrl, fileSize);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("minio 上传失败！");
            throw new RuntimeException("minio 上传失败！");
        }
    }

    @Override
    public FileReturn copy(String srcFilePath, UploadConfig configItem) {
        return null;
    }
}
